package com.yuelao.yuelao_backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuelao.yuelao_backend.common.BizException;
import com.yuelao.yuelao_backend.common.ErrorCode;
import com.yuelao.yuelao_backend.dto.UserDTO;
import com.yuelao.yuelao_backend.entity.User;
import com.yuelao.yuelao_backend.entity.UserFollow;
import com.yuelao.yuelao_backend.enums.SystemMessageType;
import com.yuelao.yuelao_backend.mapper.UserFollowMapper;
import com.yuelao.yuelao_backend.service.AchievementService;
import com.yuelao.yuelao_backend.service.SystemMessageService;
import com.yuelao.yuelao_backend.service.UserFollowService;
import com.yuelao.yuelao_backend.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserFollowServiceImpl extends ServiceImpl<UserFollowMapper, UserFollow> implements UserFollowService {

    @Resource
    private UserService userService;
    
    @Resource
    private AchievementService achievementService;
    
    @Resource
    private SystemMessageService systemMessageService;

    @Override
    @Transactional
    public boolean followUser(Long followerId, Long followedId) {
        if (followerId.equals(followedId)) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "不能关注自己");
        }

        // 检查用户是否存在
        User follower = userService.getById(followerId);
        User followed = userService.getById(followedId);
        if (follower == null || followed == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }

        // 检查是否已关注
        LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFollow::getUserId, followerId)
                .eq(UserFollow::getFollowedUserId, followedId);
        long count = count(queryWrapper);
        if (count > 0) {
            return true; // 已经关注，直接返回成功
        }

        // 记录关注关系
        UserFollow userFollow = new UserFollow();
        userFollow.setUserId(followerId);
        userFollow.setFollowedUserId(followedId);
        userFollow.setCreatedAt(LocalDateTime.now());
        boolean saved = save(userFollow);

        if (saved) {
            // 更新关注数和粉丝数
            follower.setFollowingCount(follower.getFollowingCount() + 1);
            followed.setFollowerCount(followed.getFollowerCount() + 1);
            userService.updateById(follower);
            userService.updateById(followed);
            
            // 检查关注相关成就
            achievementService.checkFollowAchievements(followerId, true);  // 关注他人
            achievementService.checkFollowAchievements(followedId, false); // 被关注
            
            // 创建系统消息通知被关注的用户
            Map<String, Object> extraData = new java.util.HashMap<>();
            extraData.put("fromUserId", followerId);
            systemMessageService.createMessage(followedId, SystemMessageType.FOLLOW, "有人关注了你", "有人关注了你，快去看看吧", extraData);
        }
        return saved;
    }

    @Override
    @Transactional
    public boolean unfollowUser(Long followerId, Long followedId) {
        if (followerId.equals(followedId)) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "不能取消关注自己");
        }

        // 检查用户是否存在
        User follower = userService.getById(followerId);
        User followed = userService.getById(followedId);
        if (follower == null || followed == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }

        // 检查是否已关注
        LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFollow::getUserId, followerId)
                .eq(UserFollow::getFollowedUserId, followedId);
        long count = count(queryWrapper);
        if (count == 0) {
            return true; // 未关注，直接返回成功
        }

        // 删除关注关系
        boolean removed = remove(queryWrapper);

        if (removed) {
            // 更新关注数和粉丝数
            follower.setFollowingCount(follower.getFollowingCount() - 1);
            followed.setFollowerCount(followed.getFollowerCount() - 1);
            userService.updateById(follower);
            userService.updateById(followed);
        }
        return removed;
    }

    @Override
    public List<UserDTO> getFollowingList(Long userId, int pageNum, int pageSize) {
        Page<UserFollow> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFollow::getUserId, userId)
                .orderByDesc(UserFollow::getCreatedAt)
                .select(UserFollow::getFollowedUserId); // 只查询被关注者ID

        Page<UserFollow> followPage = page(page, queryWrapper);

        List<Long> followedIds = followPage.getRecords().stream()
                .map(UserFollow::getUserId)
                .collect(Collectors.toList());

        if (followedIds.isEmpty()) {
            return List.of();
        }

        List<User> followedUsers = userService.listByIds(followedIds);
        return followedUsers.stream()
                .map(userService::convertToUserDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserDTO> getFollowerList(Long userId, int pageNum, int pageSize) {
        Page<UserFollow> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFollow::getFollowedUserId, userId)
                .orderByDesc(UserFollow::getCreatedAt)
                .select(UserFollow::getUserId); // 只查询关注者ID

        Page<UserFollow> followerPage = page(page, queryWrapper);

        List<Long> followerIds = followerPage.getRecords().stream()
                .map(UserFollow::getUserId)
                .collect(Collectors.toList());

        if (followerIds.isEmpty()) {
            return List.of();
        }

        List<User> followers = userService.listByIds(followerIds);
        return followers.stream()
                .map(userService::convertToUserDTO)
                .collect(Collectors.toList());
    }

    @Override
    public boolean isFollowing(Long followerId, Long followedId) {
        LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFollow::getUserId, followerId)
                .eq(UserFollow::getFollowedUserId, followedId);
        return count(queryWrapper) > 0;
    }

    @Override
    public long countFollowers(Long userId) {
        LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFollow::getFollowedUserId, userId);
        return count(queryWrapper);
    }

    @Override
    public Set<Long> getFollowedUserIds(Long followerId, Set<Long> targetUserIds) {
        if (followerId == null || targetUserIds == null || targetUserIds.isEmpty()) {
            return Collections.emptySet();
        }

        LambdaQueryWrapper<UserFollow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserFollow::getUserId, followerId)
                .in(UserFollow::getFollowedUserId, targetUserIds)
                .select(UserFollow::getFollowedUserId);

        List<UserFollow> follows = list(queryWrapper);
        return follows.stream()
                .map(UserFollow::getFollowedUserId)
                .collect(Collectors.toSet());
    }
}